/*
 * Copyright 2009 Original Author(s)
 * 
 * This file is part of Kommando
 * 
 * Kommando is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Kommando is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Kommando.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.kommando.util.osgi;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;

import ca.odell.glazedlists.BasicEventList;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.GlazedLists;

/**
 * @author Peter De Bruycker
 */
public class ServiceCollectionUtils {

    private ServiceCollectionUtils() {
        // static methods only
    }

    /**
     * Returns an {@link EventList} containing the registered services of the given type.
     * <p>
     * The {@link EventList} is kept up to date with the registered services, and is thread safe.
     * 
     * @param <T>
     *            the service type
     * @param context
     *            the {@link BundleContext}
     * @param serviceType
     *            the service type
     * @return the {@link EventList}
     */
    public static <T> EventList<T> getServiceList(final BundleContext context, final Class<T> serviceType) {
        final EventList<T> serviceList = GlazedLists.threadSafeList(new BasicEventList<T>());

        final Bundle bundle = context.getBundle();

        final ServiceTracker tracker = new ServiceTracker(context, serviceType.getName(), null) {
            @Override
            public Object addingService(ServiceReference reference) {
                T service = serviceType.cast(super.addingService(reference));
                serviceList.add(service);

                // System.out.println("adding " + service);

                return service;
            }

            @Override
            public void removedService(ServiceReference reference, Object service) {
                serviceList.remove(service);

                // System.out.println("removing " + service);

                super.removedService(reference, service);
            }
        };
        tracker.open();

        context.addBundleListener(new BundleListener() {
            @Override
            public void bundleChanged(BundleEvent event) {
                if (bundle == event.getBundle() && BundleEvent.STOPPED == event.getType()) {
                    System.out.println("stopping!!!" + context.getBundle());
                    tracker.close();
                    context.removeBundleListener(this);
                }
            }
        });

        return GlazedLists.readOnlyList(serviceList);
    }

}
